/* Declaracao visando identificar o modulo como servidor. */

#define SERVIDOR_PERSISTENCIA_POSTAGENS

/* Inclusao de arquivo com a declaracao da interface. */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "interface_persistencia.h"



/* Definicao do corpo da funcao. */

void Ler_Postagem_BD(FILE *file, int *identificador_postagem, int *identificador_autor, char data[11], int *num_avaliacoes, float *media_avaliacoes, char texto_postagem[31])
{
	char identificador_postagem_leitura[6], identificador_autor_leitura[6], data_leitura[11], media_avaliacoes_leitura[5], num_avaliacoes_leitura[2];
	int i;
	char c = '\0';

	while ((c == '\0') || (c == '\t') || (c == '\n') || (c == EOF))
	{
		if (c == EOF)
			return;
		c = fgetc(file);
	}

	i = 0;
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		identificador_postagem_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	identificador_postagem_leitura[i] = '\0';
	*identificador_postagem = atoi(identificador_postagem_leitura);

	i = 0;
	c = fgetc(file);
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		identificador_autor_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	identificador_autor_leitura[i] = '\0';
	*identificador_autor = atoi(identificador_autor_leitura);

	i = 0;
	c = fgetc(file);
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		data_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	data_leitura[i] = '\0';
	strcpy(data,data_leitura);

	i = 0;
	c = fgetc(file);
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		num_avaliacoes_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	num_avaliacoes_leitura[i] = '\0';
	*num_avaliacoes = atoi(num_avaliacoes_leitura);

	i = 0;
	c = fgetc(file);
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		media_avaliacoes_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	media_avaliacoes_leitura[i] = '\0';
	*media_avaliacoes = atof(media_avaliacoes_leitura);

	i = 0;
	c = fgetc(file);
	while (c != '#')
	{
		texto_postagem[i] = c;
		i++;
		c = fgetc(file);
	}
	i--;
	texto_postagem[i] = '\0';
	fgetc(file);
}


void Ler_Comentario_BD(FILE *file, int *identificador_postagem, int *identificador_comentario, int *identificador_autor, char data[11], char texto_comentario[21])
{
	char identificador_postagem_leitura[6], identificador_comentario_leitura[6], identificador_autor_leitura[6], data_leitura[11];
	int i;
	char c = '\0';

	while ((c == '\0') || (c == '\t') || (c == '\n') || (c == EOF))
	{
		if (c == EOF)
			return;
		c = fgetc(file);
	}

	i = 0;
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		identificador_postagem_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	identificador_postagem_leitura[i] = '\0';
	*identificador_postagem = atoi(identificador_postagem_leitura);

	i = 0;
	c = fgetc(file);
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		identificador_comentario_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	identificador_comentario_leitura[i] = '\0';
	*identificador_comentario = atoi(identificador_comentario_leitura);

	i = 0;
	c = fgetc(file);
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		identificador_autor_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	identificador_autor_leitura[i] = '\0';
	*identificador_autor = atoi(identificador_autor_leitura);

	i = 0;
	c = fgetc(file);
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		data_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	data_leitura[i] = '\0';


	i = 0;
	c = fgetc(file);
	while (c != '#')
	{
		texto_comentario[i] = c;
		i++;
		c = fgetc(file);
	}
	i--;
	texto_comentario[i] = '\0';
	fgetc(file);

	strcpy(data,data_leitura);
}




int cadastrar_postagem_persistencia(char texto_postagem[31], int identificador_postagem, bool comentavel, int identificador_autor, char data[11])
{
	FILE *file;

	int status = -1;
	float media_avaliacoes = 0;
	int num_avaliacoes = 0;

	//Verifica se o arquivo existe, se nao existe cria
	file = fopen(DATABASE_POSTAGENS, "r+");
	if (!file)
		file = fopen(DATABASE_POSTAGENS, "w");

	//Vai para o final do arquivo e escreve a postagem nele
	fseek(file, 0, SEEK_END);
	status = fprintf(file, "%d\n%d\n%s\n%d\n%f\n%s\n#\n\n\n", identificador_postagem, identificador_autor, data, num_avaliacoes, media_avaliacoes, texto_postagem);
	fclose(file);

	return status;
}



int cadastrar_comentario_persistencia(char texto_comentario[21], int identificador_comentario, int identificador_postagem, int identificador_autor, char data[11])
{
	FILE *file;
	int status = -1;

	//Verifica se o arquivo existe, se nao existe cria
	file = fopen(DATABASE_COMENTARIOS, "r+");
	if (!file)
		file = fopen(DATABASE_COMENTARIOS, "w");

	//Vai para o final do arquivo e escreve o comentario nele
	fseek(file, 0, SEEK_END);
	status = fprintf(file, "%d\n%d\n%d\n%s\n%s\n#\n\n", identificador_postagem, identificador_comentario, identificador_autor, data, texto_comentario);
	fclose(file);

	return status;
}





int remover_postagem_persistencia(int identificador_postagem, int verifica_autoria)
{
	FILE *file, *file_aux;
	int identificador = -1, num_avaliacoes = 0;
	int identificador_postagem_leitura, identificador_autor;
	float media_avaliacoes = 0;
	char texto_postagem[31], data[11];

	file_aux = fopen(DATABASE_POSTAGENS_AUXILIAR, "w");
	file = fopen(DATABASE_POSTAGENS, "r");

	//Verifica se o arquivo existe
	if (file)
	{
		//Verifica se a autoria da postagem e quem a exclui
		while(1){
			Ler_Postagem_BD(file, &identificador_postagem_leitura, &identificador_autor,
								data, &num_avaliacoes, &media_avaliacoes, texto_postagem);
			if (feof(file))
				return identificador;
			if(identificador_postagem_leitura == identificador_postagem){
				if(identificador_autor == verifica_autoria){
						break;
					}else
						return identificador - 1;
					}
				}
		rewind(file);

		//Escreve os registros no arquivo auxiliar com excecao do registro que deseja excluir
		while (1)
		{
			Ler_Postagem_BD(file, &identificador_postagem_leitura, &identificador_autor,
					data, &num_avaliacoes, &media_avaliacoes, texto_postagem);
			if (feof(file))
				break;
			if (identificador_postagem_leitura != identificador_postagem)
			{
				fprintf(file_aux, "%d\n%d\n%s\n%d\n%f\n%s\n#\n\n\n", identificador_postagem_leitura,
						identificador_autor, data, num_avaliacoes, media_avaliacoes, texto_postagem);
			}
			else identificador = identificador_postagem;
		}
	} else
		printf("\nNao foi possivel abrir o Banco de Dados.\n");

	fclose(file);
	fclose(file_aux);


	//Reescreve o arquivo com os registros sem a linha desejada
	file_aux = fopen(DATABASE_POSTAGENS_AUXILIAR, "r");
	file = fopen(DATABASE_POSTAGENS, "w");



	//Verifica se o arquivo existe
	if (file_aux)
	{
		//Escreve os registros do arquivo auxiliar no arquivo principal
		while (1)
		{
			Ler_Postagem_BD(file_aux, &identificador_postagem_leitura, &identificador_autor,
					data, &num_avaliacoes, &media_avaliacoes, texto_postagem);
			if (feof(file_aux))
				break;
			fprintf(file, "%d\n%d\n%s\n%d\n%f\n%s\n#\n\n\n", identificador_postagem_leitura,
					identificador_autor, data, num_avaliacoes, media_avaliacoes, texto_postagem);
		}
	} else
		printf("\nOcorreu um erro no Banco de Dados.\n");

	fclose(file);
	fclose(file_aux);

	//Limpa o arquivo auxiliar
	file_aux = fopen(DATABASE_POSTAGENS_AUXILIAR, "w");
	fclose(file_aux);

	identificador = 1;
	return identificador;
}


int remover_postagens_usuario_persistencia(int identificador_autor)
{
	Postagem *postagem;

	postagem = listar_postagens_persistencia();

	while (postagem != NULL)
	{
		if (postagem->identificador_autor == identificador_autor)
			remover_postagem_persistencia(postagem->identificador_postagem, identificador_autor);
		postagem = postagem->prox;
	}

	return 1;
}


int remover_comentario_persistencia(int identificador_comentario, int verifica_autoria)
{
	FILE *file, *file_aux;
	int identificador = -1;
	char texto_comentario[21], data[11];
	int identificador_comentario_leitura, identificador_postagem, identificador_autor;


	file_aux = fopen(DATABASE_COMENTARIOS_AUXILIAR, "w");
	file = fopen(DATABASE_COMENTARIOS, "r");

	//Verifica se o arquivo existe
	if (file)
	{
		//Verifica se a autoria do comentario e quem o exclui
		while(1){
			Ler_Comentario_BD(file, &identificador_postagem, &identificador_comentario_leitura,
								&identificador_autor, data, texto_comentario);
			if (feof(file))
				return identificador;
			if(identificador_comentario_leitura == identificador_comentario){
				if(identificador_autor == verifica_autoria){
					break;
				}else
					return identificador - 1;
			}
		}
		rewind(file);

		//Escreve os registros no arquivo auxiliar com excecao do registro que deseja excluir
		while (1)
		{
			Ler_Comentario_BD(file, &identificador_postagem, &identificador_comentario_leitura,
					&identificador_autor, data, texto_comentario);
			if (feof(file))
				break;
			if (identificador_comentario_leitura != identificador_comentario)
			{
				fprintf(file_aux, "%d\n%d\n%d\n%s\n%s\n#\n\n", identificador_postagem,
						identificador_comentario_leitura, identificador_autor, data, texto_comentario);
			}
			else identificador = identificador_comentario_leitura;
		}
	} else
		printf("\nNao foi possivel abrir o Banco de Dados.\n");

	fclose(file);
	fclose(file_aux);


	//Reescreve o arquivo com os registros sem a linha desejada
	file_aux = fopen(DATABASE_COMENTARIOS_AUXILIAR, "r");
	file = fopen(DATABASE_COMENTARIOS, "w");



	//Verifica se o arquivo existe
	if (file_aux)
	{
		//Escreve os registros do arquivo auxiliar no arquivo principal
		while (1)
		{
			Ler_Comentario_BD(file_aux, &identificador_postagem, &identificador_comentario_leitura,
				&identificador_autor, data, texto_comentario);
			if (feof(file_aux))
				break;
			fprintf(file, "%d\n%d\n%d\n%s\n%s\n#\n\n", identificador_postagem,
					identificador_comentario_leitura, identificador_autor, data, texto_comentario);
		}
	} else
		printf("\nOcorreu um erro no Banco de Dados.\n");

	fclose(file);
	fclose(file_aux);

	//Limpa o arquivo auxiliar
	file_aux = fopen(DATABASE_COMENTARIOS_AUXILIAR, "w");
	fclose(file_aux);

	identificador = 1;
	return identificador;
}





int remover_comentarios_usuario_persistencia(int identificador_autor)
{
	Postagem *postagem;
	Comentario *comentario;

	postagem = listar_postagens_persistencia();

	while (postagem != NULL)
	{
		comentario = listar_comentarios_persistencia(postagem->identificador_postagem);
		while (comentario != NULL)
		{
			if (comentario->identificador_autor == identificador_autor)
			{
				remover_comentario_persistencia(comentario->identificador_comentario, identificador_autor);
			}
			comentario = comentario->prox;
		}
		postagem = postagem->prox;
	}

	return 1;
}





int avaliar_postagem_persistencia(int identificador_postagem, float avaliacao)
{
	FILE *file;
	int identificador_postagem_leitura, identificador_autor, num_avaliacoes = 0;
	float media_avaliacoes = 0, nova_avaliacao;
	int status = -1;
	char texto_postagem[31], data[11];

	//Verifica se o arquivo existe
	file = fopen(DATABASE_POSTAGENS, "r+");
	if (file)
	{
		//Busca o arquivo ate encontrar o identificador
		while (1)
		{
			Ler_Postagem_BD(file, &identificador_postagem_leitura, &identificador_autor,
					data, &num_avaliacoes, &media_avaliacoes, texto_postagem);
			if (feof(file))
				break;
			if (identificador_postagem_leitura == identificador_postagem)
			{
				//Remove a postagem anterior
				remover_postagem_persistencia(identificador_postagem, identificador_autor);
				nova_avaliacao = media_avaliacoes * num_avaliacoes;
				nova_avaliacao = nova_avaliacao + avaliacao;
				num_avaliacoes++;
				media_avaliacoes = nova_avaliacao / num_avaliacoes;
				fseek(file, 0, SEEK_END);
				//Escreve a mesma postagem com avaliacao atualizada
				status = fprintf(file, "%d\n%d\n%s\n%d\n%f\n%s\n#\n\n\n", identificador_postagem,
						identificador_autor, data, num_avaliacoes, media_avaliacoes, texto_postagem);
				break;
			}
		}
	}

	fclose(file);

	return status;
}




Postagem* listar_postagens_persistencia()
{
	FILE *file;
	int identificador_postagem, identificador_autor, num_avaliacoes = 0;
	float media_avaliacoes = 0;
	char texto_postagem[31], data[11];
	bool primeira_leitura = true;
	Postagem *postagem, *aux;

	postagem = (Postagem*) malloc(sizeof(Postagem));
	aux = postagem;

	//Verifica se o arquivo existe
	file = fopen(DATABASE_POSTAGENS, "r");
	if (file)
	{
		//Busca o arquivo ate encontrar o identificador
		while (1)
		{
			Ler_Postagem_BD(file, &identificador_postagem, &identificador_autor, data,
					&num_avaliacoes, &media_avaliacoes, texto_postagem);
			if (feof(file))
			{
				if (!primeira_leitura)
					postagem->prox = NULL;
				else
					postagem = NULL;
				break;
			}
			else
			{
				if (!primeira_leitura)
				{
					postagem->prox = (Postagem*) malloc(sizeof(Postagem));
					postagem = postagem->prox;
				}
				else
					primeira_leitura = false;
			}
			//Passa os valores para a estrutura de dados
			postagem->identificador_postagem = identificador_postagem;
			postagem->identificador_autor = identificador_autor;
			strcpy(postagem->data, data);
			postagem->num_avaliacoes = num_avaliacoes;
			postagem->media_avaliacoes = media_avaliacoes;
			strcpy (postagem->texto_postagem, texto_postagem);
		}
	}
	fclose(file);

	if (postagem == NULL)
		aux = NULL;

	return aux;
}




Comentario* listar_comentarios_persistencia(int identificador_postagem)
{
	FILE *file;
	char texto_comentario[21], data[11];
	int identificador_comentario, identificador_postagem_leitura, identificador_autor;
	bool primeira_leitura = true;
	Comentario *comentario, *aux;

	comentario = (Comentario*) malloc(sizeof(Comentario));
	aux = comentario;


	// Verifica se o arquivo existe, se nao existe cria
	file = fopen(DATABASE_COMENTARIOS, "r");
	if (file)
	{
		//Busca o arquivo ate encontrar a postagem
		while (1)
		{
			Ler_Comentario_BD(file, &identificador_postagem_leitura,
					&identificador_comentario, &identificador_autor, data, texto_comentario);
			if (feof(file))
			{
				if (!primeira_leitura)
					comentario->prox = NULL;
				else
					comentario = NULL;
				break;
			}
			if (identificador_postagem == identificador_postagem_leitura)
			{
				if (!primeira_leitura)
				{
					comentario->prox = (Comentario*) malloc(sizeof(Comentario));
					comentario = comentario->prox;
				}
				else
					primeira_leitura = false;

				//Passa os valores para a estrutura de dados
				comentario->identificador_postagem = identificador_postagem;
				comentario->identificador_comentario = identificador_comentario;
				comentario->identificador_autor = identificador_autor;
				strcpy(comentario->data, data);
				strcpy (comentario->texto_comentario, texto_comentario);
			}
		}
	}
    fclose(file);

    if (comentario == NULL)
    	aux = NULL;

    return aux;
}



Postagem* busca_postagem_persistencia(int identificador_autor)
{
	FILE *file;
	int identificador_postagem, identificador_autor_leitura, num_avaliacoes = 0;
	float media_avaliacoes = 0;
	char texto_postagem[31], data[11];
	bool primeira_leitura = true;
	Postagem *postagem, *aux;

	postagem = (Postagem*) malloc(sizeof(Postagem));
	aux = postagem;

	//Verifica se o arquivo existe
	file = fopen(DATABASE_POSTAGENS, "r");
	if (file)
	{
		//Busca o arquivo ate encontrar o identificador
		while (1)
		{
			Ler_Postagem_BD(file, &identificador_postagem, &identificador_autor_leitura, data,
					&num_avaliacoes, &media_avaliacoes, texto_postagem);
			if (feof(file))
			{
				postagem->prox = NULL;
				break;
			}

			if (identificador_autor == identificador_autor_leitura)
			{
				if (!primeira_leitura)
				{
					postagem->prox = (Postagem*) malloc(sizeof(Postagem));
					postagem = postagem->prox;
				}
				else
					primeira_leitura = false;

				//Passa os valores para a estrutura de dados
				postagem->identificador_postagem = identificador_postagem;
				postagem->identificador_autor = identificador_autor_leitura;
				strcpy(postagem->data, data);
				postagem->num_avaliacoes = num_avaliacoes;
				postagem->media_avaliacoes = media_avaliacoes;
				strcpy (postagem->texto_postagem, texto_postagem);
			}
		}
	}
	fclose(file);

	return aux;
}

Comentario* busca_comentario_persistencia(int identificador_autor)
{
	FILE *file;
	char texto_comentario[21], data[11];
	int identificador_comentario, identificador_postagem, identificador_autor_leitura;
	bool primeira_leitura = true;
	Comentario *comentario, *aux;

	comentario = (Comentario*) malloc(sizeof(Comentario));
	aux = comentario;


	// Verifica se o arquivo existe, se nao existe cria
	file = fopen(DATABASE_COMENTARIOS, "r");
	if (file)
	{
		//Busca o arquivo ate encontrar a postagem
		while (1)
		{
			Ler_Comentario_BD(file, &identificador_postagem,
					&identificador_comentario, &identificador_autor_leitura, data, texto_comentario);
			if (feof(file))
			{
				comentario->prox = NULL;
				break;
			}

			if (identificador_autor == identificador_autor_leitura)
			{
				if (!primeira_leitura)
				{
					comentario->prox = (Comentario*) malloc(sizeof(Comentario));
					comentario = comentario->prox;
				}
				else
					primeira_leitura = false;

				//Passa os valores para a estrutura de dados
				comentario->identificador_postagem = identificador_postagem;
				comentario->identificador_comentario = identificador_comentario;
				comentario->identificador_autor = identificador_autor_leitura;
				strcpy(comentario->data, data);
				strcpy (comentario->texto_comentario, texto_comentario);
			}
		}
	}
	fclose(file);

	return aux;
}


void Ler_IdentificadorDB (FILE *file, int *identificador, int *livre)
{
	char identificador_leitura[6], livre_leitura[2];
	int i;
	char c = '\0';

	while ((c == '\0') || (c == '\t') || (c == '\n') || (c == EOF))
	{
		if (c == EOF)
			return;
		c = fgetc(file);
	}

	i = 0;
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		identificador_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	identificador_leitura[i] = '\0';
	*identificador = atoi(identificador_leitura);

	i = 0;
	c = fgetc(file);
	while ((c != '\t') && (c != '\n') && (c != '\0'))
	{
		livre_leitura[i] = c;
		i++;
		c = fgetc(file);
	}
	livre_leitura[i] = '\0';
	*livre=atoi(livre_leitura);
}

//Cria um arquivo pre-estabelecido contendo todos os identificadores possiveis. Inicialmente livre (1)
int criar_BD_identificadores()
{
	FILE *file;
	int i, livre, status = -1;
	livre = 1;

	file = fopen(DATABASE_IDENTIFICADORES, "w");
	for(i=0;i<10000;i++)
	{
		status = fprintf(file, "%d\t%d\n", i, livre);
	}
	fclose(file);
	return status;
}

int verificar_identificador_livre(int identificador)
{
	FILE *file;
	int *identificadorDB, *livre, status = -1;
	long localizador;
	*identificadorDB = -1;

	//Verifica se o arquivo existe, se nao existe cria o arquivo ja pre-estabelecido
	file = fopen(DATABASE_IDENTIFICADORES, "r+");
	if (!file)
	{
		status=criar_BD_identificadores();
		file=fopen(DATABASE_IDENTIFICADORES, "r+");
	}
	//Busca o numero do identificador e veja se esta livre
	while(*identificadorDB!=identificador)
	{
		Ler_IdentificadorDB(file, identificadorDB, livre);
	}
	if (*livre==1)
	{
		//Se esta livre, modifica o arquivo para nao livre e retorna status
		localizador = ftell(file);
		localizador = localizador-(sizeof(char)*2);
		fseek(file, localizador, SEEK_SET);
		fputs("0\0", file);
		fclose(file);
		return status;
	}
	else
	{
		status = -1;
		fclose(file);
		return status;
	}

}

int libera_identificador (int identificador){
	FILE *file;
	int *identificadorDB, *livre, status = -1;
	long localizador;

	file = fopen(DATABASE_IDENTIFICADORES, "r+");
		if (file)
		{
		//Procura no arquivo o identificador e libera-o novamente
		while(*identificadorDB!=identificador)
		{
			Ler_IdentificadorDB(file, identificadorDB, livre);
		}
		localizador = ftell(file);
		localizador = localizador-(sizeof(char)*2);
		fseek(file, localizador, SEEK_SET);
		fputs("1\0", file);
		fclose(file);
		return status;
		}

		else
			return status;
}
